package com.tma.mobilechart.line;

import java.util.ArrayList;
import java.util.List;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.content.Context;
import android.opengl.GLES10;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLU;
import android.view.MotionEvent;

import com.tma.mobilechart.utilitys.ZoomMultitouch;


public class LineRender3D extends GLSurfaceView implements Renderer {
	
	private LineAxisCoord3D mAxis;
	//private Line mline;
	
	/* Rotation values */
	private float xRot;					//X Rotation
	private float yRot;					//Y Rotation
		
	private float oldX;
    private float oldY;
    private final float TOUCH_SCALE = 0.2f;		//Proved to be good for normal rotation
    
    private float z = -5.0f;			//Depth Into The Screen
    
    private boolean fZoom = false;
    
    
    static final int NONE = 0;
	static final int DRAG = 1;
	static final int ZOOM = 2;
	int mode = NONE;
	       
    private List<Line3D> mLine;
        
    private LineInputData mInputData;
  	
	public LineRender3D(Context context, LineInputData mInputData)
	{	super(context);
		
		this.setRenderer(this);	
		
		this.mInputData = mInputData;
		
		float[] findMax;		
		findMax = new float[this.mInputData.getlData().size()];
		for(int i = 0; i < findMax.length; i++)
		{
			findMax[i] = findMaxIndex(this.mInputData.getlData().get(i).getlYValue());
		}
		
		this.mInputData.setMaxValueY(findMaxIndex(findMax));
		
		mLine = new ArrayList<Line3D>();
		for(int i = 0; i < mInputData.getlData().size(); i++)
		{
			Line3D _mline = new Line3D(this.mInputData, i, this.mInputData.getlData().get(i).getlColor());
			mLine.add(_mline);
		}		
		mAxis = new LineAxisCoord3D();
	}
	
	@Override
	public void onDrawFrame(GL10 gl) {
		// TODO Auto-generated method stub		
		gl.glClear(GLES10.GL_COLOR_BUFFER_BIT|GLES10.GL_DEPTH_BUFFER_BIT);		
		gl.glLoadIdentity();
		gl.glTranslatef(-0.5f, 0.0f, z);
		
		//Rotate around the axis based on the rotation matrix (rotation, x, y, z)
		gl.glRotatef(xRot, 1.0f, 0.0f, 0.0f);	//X
		gl.glRotatef(yRot, 0.0f, 1.0f, 0.0f);	//Y
			
		for(int i = 0; i < mLine.size(); i++)
		{
			mLine.get(i).draw(gl);
		}
		mAxis.draw(gl);
		
		if (ZoomMultitouch.m_GestureMode == 2 && ZoomMultitouch.m_PinchFlag == 1) 
		{
			ZoomMultitouch.setClipping(gl, ZoomMultitouch.origwidth, ZoomMultitouch.origheight);
			ZoomMultitouch.m_PinchFlag = 0;
		}
				
	}
	
	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
		// TODO Auto-generated method stub
		if(height == 0) 
		{                       //Prevent A Divide By Zero By
			height = 1;                         //Making Height Equal One
		}
		gl.glViewport(0, 0, width, height);     //Reset The Current Viewport
		ZoomMultitouch.origwidth = width;
		ZoomMultitouch.origheight = height;
		gl.glMatrixMode(GL10.GL_PROJECTION);    //Select The Projection Matrix
		gl.glLoadIdentity();                    //Reset The Projection Matrix
		ZoomMultitouch.setClipping(gl, width, height);
		//Calculate The Aspect Ratio Of The Window
		GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);
		gl.glMatrixMode(GL10.GL_MODELVIEW);     //Select The Modelview Matrix
		gl.glLoadIdentity();                    //Reset The Modelview Matrix

	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		// TODO Auto-generated method stub
		gl.glClearColor(0.1f, 0.5f, 0.5f, 0.5f);
		gl.glShadeModel(GL10.GL_SMOOTH); 			//Enable Smooth Shading
		gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); 	//Black Background
		gl.glClearDepthf(1.0f); 					//Depth Buffer Setup
		gl.glEnable(GL10.GL_DEPTH_TEST); 			//Enables Depth Testing
		gl.glDepthFunc(GL10.GL_LEQUAL); 			//The Type Of Depth Testing To Do
		
		//Really Nice Perspective Calculations
		gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); 
		
	}
	
	@Override		 
	public boolean onTouchEvent(MotionEvent ev) 
	{
			boolean retval = true;
			float x = ev.getX();
		    float y = ev.getY();
		    
		    float dx,dy;
			
			switch (ev.getAction() & MotionEvent.ACTION_MASK) 
			{
				case MotionEvent.ACTION_DOWN:
					mode = DRAG;
					break;
					
				case MotionEvent.ACTION_UP:
				case MotionEvent.ACTION_POINTER_UP:
					mode = NONE;
					ZoomMultitouch.m_LastTouchPoint.x = ev.getX();
					ZoomMultitouch.m_LastTouchPoint.y = ev.getY();
					break;
					
				case MotionEvent.ACTION_POINTER_DOWN:
					ZoomMultitouch.m_OldDist = ZoomMultitouch.spacing(ev);//distance
		
					ZoomMultitouch.midPoint(ZoomMultitouch.m_MidPoint, ev);//mid point
					mode = ZOOM;
					ZoomMultitouch.m_StartFOV = ZoomMultitouch.getFieldOfView();

					ZoomMultitouch.m_LastTouchPoint.x = ZoomMultitouch.m_MidPoint.x;
					ZoomMultitouch.m_LastTouchPoint.y = ZoomMultitouch.m_MidPoint.y;
					ZoomMultitouch.m_CurrentTouchPoint.x = ZoomMultitouch.m_MidPoint.x;
					ZoomMultitouch.m_CurrentTouchPoint.y = ZoomMultitouch.m_MidPoint.y;
					
					break;
					
				case MotionEvent.ACTION_MOVE:
					dx = x - oldX;
				    dy = y - oldY;

					if (mode == DRAG) 
					{	
						retval = ZoomMultitouch.handleDragGesture(ev);
						xRot += dy * TOUCH_SCALE;
			    	    yRot += dx * TOUCH_SCALE;
					} 
					else if (mode == ZOOM) 
					{
						retval = ZoomMultitouch.handlePinchGesture(ev);
					}
					requestRender();
					break;
			}
			
			oldX = x;
	        oldY = y;
			return retval;
	}
		
	
	public float findMaxIndex(float[] array)
	{
		float result = 0;		
		result = array[0];
		for(int i = 0; i< array.length; i++)
		{
			if(result <= array[i])
			{
				result = array[i];
			}
		}
		return result;
	}
		
}
